package com.example.mytest

import android.app.Activity
import android.app.Instrumentation
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.util.LruCache
import android.view.View
import androidx.annotation.RequiresApi
import kotlinx.android.synthetic.main.activity_main.*
import java.io.ByteArrayOutputStream
import java.lang.ref.WeakReference
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import java.math.BigDecimal
import java.text.SimpleDateFormat
import java.util.*

class MainActivity : Activity() {

    val images = mutableListOf(R.mipmap.image1, R.mipmap.image2, R.mipmap.image3)
    var pos = 0
    val open = BitmapFactory.Options()
    var mBitmap: Bitmap? = null
    val lruCache =
        LruCache<String, WeakReference<Bitmap>>((Runtime.getRuntime().maxMemory() / 8).toInt())

    override fun onCreate(savedInstanceState: Bundle?) {
        Log.e("tag", "onCreate: ")
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        open.inPreferredConfig = Bitmap.Config.ARGB_8888
        val densityDpi = resources.displayMetrics.densityDpi
        open.inScreenDensity = 1000
        open.inSampleSize = 10
        Log.e("TAG", "onCreate: " + densityDpi + "   inDensity=" + open.inDensity)
    }

    fun addImage(view: View) {
        mBitmap = getLruBitmap(images[pos])
        Log.e("TAG", "addImage: " + sunImageSize(mBitmap!!))
        img.setImageBitmap(mBitmap!!)
    }

    fun switchImage(view: View) {
        pos++
        if (pos >= images.size) {
            pos = 0
        }
        mBitmap = getLruBitmap(images[pos])
        Log.e("TAG", "switchImage: " + sunImageSize(mBitmap!!))
        img.setImageBitmap(mBitmap)
//        img.setImageResource(images[pos])
    }

    private fun getLruBitmap(int: Int): Bitmap {
        var weakBitmap = lruCache.get(int.toString())
        if (weakBitmap?.get() == null) {
            weakBitmap = WeakReference(getBitmap(mBitmap, int))
            lruCache.put(int.toString(), weakBitmap)
        }
        return weakBitmap.get()!!
    }

    private fun getBitmap(bitmap: Bitmap?, int: Int): Bitmap {
        val options = BitmapFactory.Options()
        options.inDensity = resources.displayMetrics.densityDpi
        options.inJustDecodeBounds = true
        BitmapFactory.decodeResource(resources, int, options)
        if (bitmap != null && optionWithBitmap(bitmap, options)) {
            Log.e("TAG", "lruBitmap: 复用")
            options.inMutable = true
            options.inBitmap = mBitmap
        }
        options.inJustDecodeBounds = false
        val decodeResource = BitmapFactory.decodeResource(resources, int, options)
        val outputStream = ByteArrayOutputStream()
        val compress = decodeResource.compress(Bitmap.CompressFormat.PNG, 50, outputStream)
        Log.e("TAG", "compress: " + compress)
//        if (compress) decodeResource.
        val bytes = outputStream.toByteArray();
        val decodeByteArray = BitmapFactory.decodeByteArray(bytes, 0, bytes.size / 4)
        return decodeByteArray
    }

    @RequiresApi(Build.VERSION_CODES.KITKAT)
    private fun optionWithBitmap(bitmap: Bitmap, option: BitmapFactory.Options): Boolean {
        Log.e(
            "TAG",
            "optionWithBitmap: outWidth=" + option.outWidth + "  height=" + option.outHeight + "  Options=" + option.inDensity
        )
        val width = option.outWidth / Math.max(option.inSampleSize, 1)
        val height = option.outHeight / Math.max(option.inSampleSize, 1)
        Log.e(
            "TAG",
            "optionWithBitmap: " + bitmap.allocationByteCount + "  " + (width * height * 4)
        )
//       return false
        return bitmap.allocationByteCount >= (width * height * 4)
    }
}

fun sunImageSize(bitmap: Bitmap): Double {
    val toDouble = BigDecimal(bitmap.allocationByteCount).divide(BigDecimal(1024 * 1024)).toDouble()
    Log.e(
        "TAG",
        "sunImageSize: " + bitmap.allocationByteCount + "-->" + toDouble + "  width=" + bitmap.width + "  heigth=" + bitmap.height + "  自算" + (bitmap.width * bitmap.height * 4)
    )

    return toDouble
}


//suspend fun main() {
//    val ticker = ticker(1000, 0)
//    withTimeoutOrNull(10000) {
//        ticker.receive()
//        MLog.mlog("1111")
//    }
//    delay(10000)
//}


object MLog {
    fun mlog(msg: Any) {
        val format = SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(Date())
        val name = Thread.currentThread().name
        println("$format(${System.currentTimeMillis()}) * $name->$msg")
    }
}

interface People {
    fun onEat()

    fun onSleep()
}

class Man : People {
    override fun onEat() {
        System.out.println("男人 - 吃饭")
    }

    override fun onSleep() {
        System.out.println("男人 - 睡觉")
    }
}


class MyIn(val people: People) : InvocationHandler {

    override fun invoke(proxy: Any, method: Method, args: Array<out Any>?): Any? {
        System.out.println("p=="+people)
        System.out.println("method=="+method.name)
        val invoke = method.invoke(people, *args.orEmpty())
        System.out.println("invoke=="+invoke)
        return invoke
    }
}

fun main(args: Array<String>) {

    val man = Man()

    val instrumentation = MyIn(man)

    val newProxyInstance = Proxy.newProxyInstance(
        People::class.java.classLoader,
        arrayOf(People::class.java),
        instrumentation
    ) as People

    newProxyInstance.onEat()
    newProxyInstance.onSleep()

}